package com.immediatus.engine.primitive;

import com.immediatus.engine.collision.LineCollisionChecker;
import com.immediatus.engine.collision.RectangularCollisionChecker;
import com.immediatus.engine.contracts.IShape;
import com.immediatus.engine.shape.RectangularShape;
import com.immediatus.engine.shape.Shape;
import com.immediatus.graphics.camera.Camera;
import com.immediatus.graphics.util.OpenGLWrapper;
import com.immediatus.graphics.vertex.LineVertexBuffer;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

public class Line extends Shape{
    private static final float LINEWIDTH_DEFAULT = 1.0f;

    protected float _X2;
    protected float _Y2;

    private float _lineWidth;
    private final LineVertexBuffer _lineVertexBuffer;


    public Line(final float x1_, final float y1_, final float x2_, final float y2_){
        this(x1_, y1_, x2_, y2_, LINEWIDTH_DEFAULT);
    }

    public Line(final float x1_, final float y1_, final float x2_, final float y2_, final float _lineWidth){
        super(x1_, y1_);

        this._X2 = x2_;
        this._Y2 = y2_;

        this._lineWidth = _lineWidth;

        this._lineVertexBuffer = new LineVertexBuffer(GL11.GL_STATIC_DRAW, true);
        this.updateVertexBuffer();

        final float width = this.getWidth();
        final float height = this.getHeight();

        final float centerX =  width * 0.5f;
        final float centerY =  height * 0.5f;

        this.setRotationCenterX(centerX);
        this.setRotationCenterY(centerY);

        this.setScaleCenterX(centerX);
        this.setScaleCenterY(centerY);
    }

    @Override
    public float getX(){
        return super.getX();
    }

    @Override
    public float getY(){
        return super.getY();
    }

    public float getX1(){
        return super.getX();
    }

    public float getY1(){
        return super.getY();
    }

    public float getX2(){
        return this._X2;
    }

    public float getY2(){
        return this._Y2;
    }

    public float getLineWidth(){
        return this._lineWidth;
    }

    public void setLineWidth(final float _lineWidth){
        this._lineWidth = _lineWidth;
    }

    @Override
    public float getBaseHeight(){
        return this._Y2 - this.getX();
    }

    @Override
    public float getBaseWidth(){
        return this._X2 - this.getX();
    }

    @Override
    public float getHeight(){
        return this._Y2 - this.getY();
    }

    @Override
    public float getWidth(){
        return this._X2 - this.getX();
    }

    @Override
    public void setPosition(final float x_, final float y_){
        final float dX = this.getX() - x_;
        final float dY = this.getY() - y_;

        super.setPosition(x_, y_);

        this._X2 += dX;
        this._Y2 += dY;
    }

    public void setPosition(final float x1_, final float y1_, final float x2_, final float y2_){
        this._X2 = x2_;
        this._Y2 = y2_;

        super.setPosition(x1_, y1_);

        this.updateVertexBuffer();
    }

    @Override
    protected boolean isCulled(final Camera pCamera){
        return pCamera.isLineVisible(this);
    }

    @Override
    protected void onInitDraw(final GL10 gl_){
        super.onInitDraw(gl_);
        OpenGLWrapper.disableTextures(gl_);
        OpenGLWrapper.disableTexCoordArray(gl_);
        OpenGLWrapper.lineWidth(gl_, this._lineWidth);
    }

    @Override
    public LineVertexBuffer getVertexBuffer(){
        return this._lineVertexBuffer;
    }

    @Override
    protected void onUpdateVertexBuffer(){
        this._lineVertexBuffer.update(0, 0, this._X2 - this.getX(), this._Y2 - this.getY());
    }

    @Override
    protected void drawVertices(final GL10 gl_, final Camera camera_){
        gl_.glDrawArrays(GL10.GL_LINES, 0, LineVertexBuffer.VERTICES_PER_LINE);
    }

    @Override
    public float[] getLayerCenterCoordinates(){
        return null;
    }

    @Override
    public boolean contains(final float x_, final float y_){
        return false;
    }

    @Override
    public float[] convertLayerToLocalCoordinates(final float x_, final float y_){
        return null;
    }


    @Override
    public float[] convertLocalToLayerCoordinates(final float x_, final float y_){
        return null;
    }

    @Override
    public boolean collidesWith(final IShape shape_){
        if (shape_ instanceof Line){
            final Line otherLine = (Line) shape_;
            return LineCollisionChecker.checkLineCollision(this.getX(), this.getY(), this._X2, this._Y2, otherLine.getX(), otherLine.getY(), otherLine._X2, otherLine._Y2);
        } else if (shape_ instanceof RectangularShape){
            final RectangularShape rectangularShape = (RectangularShape) shape_;
            return RectangularCollisionChecker.checkCollision(rectangularShape, this);
        } else{
            return false;
        }
    }
}
